/**==============================================================================
            Copyright (c) 2013 Moritz Hader, Marcel Schrder
            All Rights Reserved.

	@file  HeimdallRenderer.java

	@brief The renderer implementation of the anroid GLSurfaceView. In here, we 
	define how the rendering-metrics need to be altered in case the SurfaceView 
	changes (i.e. size) and when it is created. Also we define the update-loop in 
	which we will call the native-code function that draws our content. Please note, 
	that, allthougt the parameters are of the type GL10 (that is, EGL 1.x), the actual 
	rendering in native-code will be of the type EGL2.0.

  This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
==============================================================================*/
package de.ibm.dhbw.heimdall.egl;

import java.util.Collection;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import de.ibm.dhbw.heimdall.HeimdallAR;

import android.opengl.GLSurfaceView;

/**
 * @author moritzhader
 *
 */
public class HeimdallRenderer implements GLSurfaceView.Renderer{
	private static Logger Log = Logger.getLogger(HeimdallRenderer.class.getCanonicalName());
	
	private boolean isRunning;
	private HeimdallAR heimdallMain;
	private long timeBegin;
	private float tpf;
	/*
	 * This lock is used when the currentTransMat is accessed. It is used as semaphore to
	 * ensure only one process can access the list at the same time
	 */
	private Object lock = new Object();
	
	/*
	 * List of the current transformation Matrices that are available within the rendering. Note that the actual values of the TMatrices are
	 * determined by the QCAR-Framework and remain hidden from the Java-Instance.
	 */
	//private Collection<Integer> currentTransMat; 
	private int[] currentTransMat;
	
	
	private native int[] renderUpdate();
	private native void renderInit();
	
	//Load the native library into the code
	static{
		HeimdallAR.LoadNativeLib("HeimdallARNative");
	}
		
	public HeimdallRenderer(HeimdallAR hAR){
		this.heimdallMain = hAR;
		//this.currentTransMat = new LinkedList<Integer>(); //Use linked list, as values are simply added
	}
	
	@Override
	public void onDrawFrame(GL10 gl) {
		
		if(this.isRunning){
			this.timeBegin = System.currentTimeMillis();
			
			//Clean up the current translation-matrix list
			//this.currentTransMat.clear();
			
			//Call the native rendering system
			updateCurrentTransMat(renderUpdate());
			
			//Calculate the time per frame
			long diff = System.currentTimeMillis() - this.timeBegin;
			/*
			 * Diff contains the time this frame required for rendering. Thus, the Framerate equals 60000/diff
			 * the time per frame ranges between 1 and 0 and is calculated by 1/Framerate, thus 1/60000/diff => diff/60000
			 * Another nice sideeffect is, that no check for zero diff is necessary ;-)
			 */
			this.tpf = (float)diff/60000;
			
			this.heimdallMain.update(this.tpf);
		}
	}

	@Override
	public void onSurfaceChanged(GL10 gl, int width, int height) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onSurfaceCreated(GL10 gl, EGLConfig config) {
		// TODO Auto-generated method stub
		renderInit();
	}

	public boolean isRunning() {
		return isRunning;
	}

	public void setRunning(boolean isRunning) {
		this.isRunning = isRunning;
	}
	
	/**
	 * This method updates the current transMat using the given array. With any luck,
	 * this will prevent the emty-block problem faced during execution.
	 * @param id
	 */
	public void updateCurrentTransMat(int[] elements){
		synchronized (lock) {
			
			this.currentTransMat = elements;
			
		}
	}
	
	public int[] getcurrentTransMat(){
		synchronized (lock) {
			return this.currentTransMat;
		}
	}

}
